#include "binary_tree.h"
#include <iostream>
#include <string.h>

using namespace binarytree;

BinaryNode::BinaryNode()
{
    this->m_data = 0;
    this->m_left = NULL;
    this->m_right = NULL;
}

BinaryNode::BinaryNode(int d)
{
    this->m_data = d;
    this->m_left = NULL;
    this->m_right = NULL;
}

void BinaryNode::SetData(int d)
{
    this->m_data = d;
}

void BinaryNode::SetLeft(BinaryNode* l)
{
    this->m_left = l;
}

void BinaryNode::SetRight(BinaryNode* r)
{
    this->m_right = r;
}

int BinaryNode::GetData()
{
    return this->m_data;
}

BinaryNode* BinaryNode::GetLeft()
{
    return this->m_left;
}

BinaryNode* BinaryNode::GetRight()
{
    return this->m_right;
}

//////////////////////////////////////////////////
BinaryTree::BinaryTree(int cap)
{
    this->m_root = NULL;
    this->m_content = new BinaryNode[cap];
    this->m_size = 0;
    this->m_cap = cap;
}

BinaryTree::~BinaryTree()
{
    if (this->m_content != NULL)
        delete this->m_content;
}

void BinaryTree::TreeInsert(int d)
{
      if (this->m_size == this->m_cap)
          return;

       this->m_content[this->m_size].SetData(d);

      if (this->m_size == 0)
      {
          this->m_root = &this->m_content[0];
          ++this->m_size;
          return;
      }

      if (this->m_size%2 == 0)
      {
          this->m_content[this->m_size/2-1].SetRight(&this->m_content[this->m_size]);
      }
      else
      {
          this->m_content[this->m_size/2].SetLeft(&this->m_content[this->m_size]);
      }
      ++this->m_size;
}

void BinaryTree::Preorder()
{
     this->preorderhelper(this->m_root);
     std::cout << std::endl;
}

void BinaryTree::preorderhelper(BinaryNode* node)
{
    if (node == NULL)
        return;

    std::cout << node->GetData() << " ";

    this->preorderhelper(node->GetLeft());

    this->preorderhelper(node->GetRight());
}

void BinaryTree::Inorder()
{
    this->inorderhelper(this->m_root);
    std::cout << std::endl;
}

void BinaryTree::inorderhelper(BinaryNode* node)
{
    if (node == NULL)
        return;

    this->inorderhelper(node->GetLeft());

    std::cout << node->GetData() << " ";

    this->inorderhelper(node->GetRight());
}

void BinaryTree::Postorder()
{
    this->postorderhelper(this->m_root);
    std::cout << std::endl;
}

void BinaryTree::postorderhelper(BinaryNode* node)
{
    if (node == NULL)
        return;

    this->postorderhelper(node->GetLeft());

    this->postorderhelper(node->GetRight());

    std::cout << node->GetData() << " ";
}

void BinaryTree::Levelorder()
{
    for(int i = 0; i < this->m_size; ++i)
    {
        std::cout << this->m_content[i].GetData() << " ";
    }
    std::cout << std::endl;
}
